package org.simpatia;

import java.io.File;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

public class AgentClassLoader extends URLClassLoader {

    private String simpatiaHome;

    public AgentClassLoader() {
        super(getUrls(null), null);
    }

    /**
     * This constructor should be used if AgentClassLoader class in standard classpath.
     * In this case it is impossible to locate Simpatia home by AgentClassLoader location.
     * @param simpatiaHome home folder of Simpatia and its libs
     */
    public AgentClassLoader(String simpatiaHome) {
        super(getUrls(simpatiaHome), null);
        this.simpatiaHome = simpatiaHome;
    }

    private static URL[] getUrls(String simpatiaHomeLocation) {
        try {
            URL simpatiaJarLocation = getSimpatiaJarLocation();

            if(simpatiaHomeLocation == null) {
                simpatiaHomeLocation = getDefaultSimpatiaHome();
            }

            File simpatiaLib = new File(simpatiaHomeLocation + "/lib");

            List<URL> urls = new ArrayList<URL>();
            urls.add(simpatiaJarLocation);
            for(File lib : simpatiaLib.listFiles()) {
                if(!lib.isDirectory()) {
                    URL libUrl = lib.toURI().toURL();
                    urls.add(libUrl);
                }
            }

            return urls.toArray(new URL[urls.size()]);

        } catch (IOException e) {
           throw new RuntimeException(e);
        }
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        return super.findClass(name);
    }

    private static URL getSimpatiaJarLocation() {
        return AgentClassLoader.class.getProtectionDomain().getCodeSource().getLocation();
    }

    private static String getDefaultSimpatiaHome() {
        URL simpatiaJarLocation = getSimpatiaJarLocation();
        return simpatiaJarLocation.getPath().substring(0, simpatiaJarLocation.getPath().lastIndexOf("/") + 1);
    }

    public String getSimpatiaHome() {
        if(simpatiaHome != null) {
            return simpatiaHome;
        } else {
            return getDefaultSimpatiaHome();
        }
    }
}
